package com.insight.service;

import com.insight.entity.MetadataColumn;
import com.insight.entity.MetadataTable;
import com.insight.repository.MetadataColumnRepository;
import com.insight.repository.MetadataTableRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * T100: MetadataSearchService实现
 * 元数据搜索服务,支持全文搜索(BM25算法)和多维度筛选
 *
 * 功能特性:
 * 1. 表名/字段名模糊搜索
 * 2. 表注释/字段注释搜索(支持中文)
 * 3. 数据类型筛选
 * 4. 组合搜索(表名+字段名、表名+数据类型)
 * 5. 全文搜索(BM25相关性评分)
 * 6. 分页排序支持
 *
 * @author Insight Team
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MetadataSearchService {

    private final MetadataTableRepository tableRepository;
    private final MetadataColumnRepository columnRepository;

    /**
     * 根据表名搜索表元数据
     * 支持模糊匹配,不区分大小写
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果
     */
    public Page<MetadataTable> searchTablesByName(String keyword, Pageable pageable) {
        log.debug("Searching tables by name: keyword={}", keyword);
        return tableRepository.searchByTableName(keyword, pageable);
    }

    /**
     * 根据表注释搜索表元数据
     * 支持中文分词搜索
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果
     */
    public Page<MetadataTable> searchTablesByComment(String keyword, Pageable pageable) {
        log.debug("Searching tables by comment: keyword={}", keyword);
        return tableRepository.searchByTableComment(keyword, pageable);
    }

    /**
     * 全文搜索表元数据
     * 使用ParadeDB BM25算法进行相关性排序
     * 搜索范围: 表名 + 表注释
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果,按BM25评分降序排列
     */
    public Page<MetadataTable> searchTablesByFullText(String keyword, Pageable pageable) {
        log.debug("Full-text searching tables: keyword={}", keyword);
        return tableRepository.searchByFullText(keyword, pageable);
    }

    /**
     * 根据列名搜索列元数据
     * 支持模糊匹配,不区分大小写
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    public Page<MetadataColumn> searchColumnsByName(String keyword, Pageable pageable) {
        log.debug("Searching columns by name: keyword={}", keyword);
        return columnRepository.searchByColumnName(keyword, pageable);
    }

    /**
     * 根据列注释搜索列元数据
     * 支持中文分词搜索
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    public Page<MetadataColumn> searchColumnsByComment(String keyword, Pageable pageable) {
        log.debug("Searching columns by comment: keyword={}", keyword);
        return columnRepository.searchByColumnComment(keyword, pageable);
    }

    /**
     * 根据数据类型筛选列元数据
     * 精确匹配数据类型
     *
     * @param dataType 数据类型 (例如: VARCHAR, BIGINT, INT, DECIMAL)
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    public Page<MetadataColumn> searchColumnsByDataType(String dataType, Pageable pageable) {
        log.debug("Searching columns by data type: dataType={}", dataType);
        return columnRepository.findByDataType(dataType, pageable);
    }

    /**
     * 组合搜索: 根据表名和列名查找列元数据
     * 先根据表名查找表,再根据列名查找列
     *
     * @param tableName  表名
     * @param columnName 列名
     * @return 列元数据,如果不存在返回null
     */
    public MetadataColumn searchColumnByTableAndName(String tableName, String columnName) {
        log.debug("Searching column by table and name: tableName={}, columnName={}", tableName, columnName);

        // 先查找表
        MetadataTable table = tableRepository.findByTableName(tableName)
                .orElse(null);

        if (table == null) {
            log.debug("Table not found: tableName={}", tableName);
            return null;
        }

        // 再查找列
        return columnRepository.findByTableAndColumnName(table, columnName)
                .orElse(null);
    }

    /**
     * 组合搜索: 根据表名和数据类型查找列元数据
     * 先根据表名查找表,再根据数据类型筛选列
     *
     * @param tableName 表名
     * @param dataType  数据类型
     * @param pageable  分页参数
     * @return 列元数据分页结果
     */
    public Page<MetadataColumn> searchColumnsByTableAndDataType(
            String tableName, String dataType, Pageable pageable) {
        log.debug("Searching columns by table and data type: tableName={}, dataType={}", tableName, dataType);

        // 先查找表
        MetadataTable table = tableRepository.findByTableName(tableName)
                .orElse(null);

        if (table == null) {
            log.debug("Table not found: tableName={}", tableName);
            return Page.empty(pageable);
        }

        // 再根据数据类型筛选列
        return columnRepository.findByTableAndDataType(table, dataType, pageable);
    }
}
